#include <iostream>
#include <vector>
#include <semaphore.h>
#include <pthread.h>
template <class T>
class RingQueue
{
public:
    RingQueue(int cap = 10)
        : _ring_queue(cap), _cap(cap), _producer_step(0), _consumer_step(0)
    {
        sem_init(&_room_sem, 0, _cap);
        sem_init(&_data_sem, 0, 0);
        pthread_mutex_init(&_producer_mutex, nullptr);
        pthread_mutex_init(&_consumer_mutex, nullptr);
    }
    void Enqueue(const T &in)
    {
        sem_wait(&_room_sem);//对空间进行--操作（P操作）
        pthread_mutex_lock(&_producer_mutex);//加锁为了只允许一个生产者进入
        _ring_queue[_producer_step++]=in;
        _producer_step%=_cap;
        pthread_mutex_unlock(&_producer_mutex);
        sem_post(&_data_sem);//对数据进行++操作（V操作）
    }
    void Pop(T *out)
    {
        sem_wait(&_data_sem);
        pthread_mutex_lock(&_consumer_mutex);
        *out=_ring_queue[_consumer_step++];
        _consumer_step%=_cap;
        pthread_mutex_unlock(&_consumer_mutex);
        sem_post(&_room_sem);
    }
    ~RingQueue()
    {
        sem_destroy(&_room_sem);
        sem_destroy(&_data_sem);
        pthread_mutex_destroy(&_producer_mutex);
        pthread_mutex_destroy(&_consumer_mutex);
    }

private:
    std::vector<T> _ring_queue;
    int _cap;
    // 生产者和消费者的下标
    int _producer_step;
    int _consumer_step;

    sem_t _room_sem; // 生产者关心
    sem_t _data_sem; // 消费者关心

    pthread_mutex_t _producer_mutex; // 生产者之间去竞争锁，竞争锁成功进入环形队列
    pthread_mutex_t _consumer_mutex;
};